"""
配置验证工具

提供配置文件验证和诊断功能
"""

import json
import os
from pathlib import Path
from typing import Dict, List, Any, Optional, Tuple

import yaml
from pydantic import ValidationError

from .settings import AppConfig, ConfigManager


class ConfigValidator:
    """配置验证器"""
    
    def __init__(self, config_manager: Optional[ConfigManager] = None):
        """
        初始化配置验证器
        
        Args:
            config_manager: 配置管理器实例
        """
        self.config_manager = config_manager or ConfigManager()
    
    def validate_config_file(self, config_path: str) -> Tuple[bool, List[str], Optional[AppConfig]]:
        """
        验证配置文件
        
        Args:
            config_path: 配置文件路径
            
        Returns:
            (是否有效, 错误列表, 配置对象)
        """
        errors = []
        config = None
        
        try:
            # 检查文件是否存在
            if not Path(config_path).exists():
                errors.append(f"配置文件不存在: {config_path}")
                return False, errors, None
            
            # 尝试加载配置
            config = self.config_manager.load_config(config_path)
            
        except yaml.YAMLError as e:
            errors.append(f"YAML格式错误: {e}")
        except json.JSONDecodeError as e:
            errors.append(f"JSON格式错误: {e}")
        except ValidationError as e:
            for error in e.errors():
                field = " -> ".join(str(x) for x in error['loc'])
                errors.append(f"字段 '{field}': {error['msg']}")
        except Exception as e:
            errors.append(f"配置加载失败: {e}")
        
        return len(errors) == 0, errors, config
    
    def validate_environment_variables(self) -> Tuple[bool, List[str]]:
        """
        验证环境变量
        
        Returns:
            (是否有效, 错误列表)
        """
        errors = []
        required_vars = [
            "SILICONFLOW_API_KEY"
        ]
        
        for var in required_vars:
            if not os.getenv(var):
                errors.append(f"缺少必需的环境变量: {var}")
        
        return len(errors) == 0, errors
    
    def validate_proxy_config(self, config: AppConfig) -> Tuple[bool, List[str]]:
        """
        验证代理配置
        
        Args:
            config: 应用配置
            
        Returns:
            (是否有效, 错误列表)
        """
        errors = []
        proxy = config.browser.proxy
        
        if proxy.enabled:
            # 检查代理类型
            if proxy.type not in ['socks5', 'http', 'https']:
                errors.append(f"不支持的代理类型: {proxy.type}")
            
            # 检查端口范围
            if not 1 <= proxy.port <= 65535:
                errors.append(f"代理端口超出范围: {proxy.port}")
            
            # 检查主机地址
            if not proxy.host:
                errors.append("代理主机地址不能为空")
        
        return len(errors) == 0, errors
    
    def validate_ai_config(self, config: AppConfig) -> Tuple[bool, List[str]]:
        """
        验证AI配置
        
        Args:
            config: 应用配置
            
        Returns:
            (是否有效, 错误列表)
        """
        errors = []
        ai = config.ai
        
        # 检查API密钥
        if not ai.api_key:
            errors.append("AI API密钥不能为空")
        
        # 检查基础URL
        if not ai.base_url:
            errors.append("AI API基础URL不能为空")
        elif not ai.base_url.startswith(('http://', 'https://')):
            errors.append("AI API基础URL必须以http://或https://开头")
        
        # 检查超时时间
        if ai.timeout < 1:
            errors.append("AI API超时时间不能少于1秒")
        
        # 检查重试次数
        if ai.max_retries < 0:
            errors.append("AI API最大重试次数不能为负数")
        
        return len(errors) == 0, errors
    
    def validate_logging_config(self, config: AppConfig) -> Tuple[bool, List[str]]:
        """
        验证日志配置
        
        Args:
            config: 应用配置
            
        Returns:
            (是否有效, 错误列表)
        """
        errors = []
        logging = config.logging
        
        # 检查日志级别
        valid_levels = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
        if logging.level.upper() not in valid_levels:
            errors.append(f"无效的日志级别: {logging.level}")
        
        # 检查日志文件路径
        if not logging.file:
            errors.append("日志文件路径不能为空")
        else:
            log_dir = Path(logging.file).parent
            if not log_dir.exists():
                try:
                    log_dir.mkdir(parents=True, exist_ok=True)
                except Exception as e:
                    errors.append(f"无法创建日志目录: {e}")
        
        # 检查备份数量
        if logging.backup_count < 0:
            errors.append("日志备份数量不能为负数")
        
        return len(errors) == 0, errors
    
    def validate_security_config(self, config: AppConfig) -> Tuple[bool, List[str]]:
        """
        验证安全配置
        
        Args:
            config: 应用配置
            
        Returns:
            (是否有效, 错误列表)
        """
        errors = []
        security = config.security
        
        # 检查加密配置
        if security.encryption_enabled and not security.encryption_password:
            errors.append("启用加密时必须提供加密密码")
        
        # 检查API速率限制
        if security.api_rate_limit < 1:
            errors.append("API速率限制不能少于1")
        
        # 检查最大并发请求数
        if security.max_concurrent_requests < 1:
            errors.append("最大并发请求数不能少于1")
        
        return len(errors) == 0, errors
    
    def validate_performance_config(self, config: AppConfig) -> Tuple[bool, List[str]]:
        """
        验证性能配置
        
        Args:
            config: 应用配置
            
        Returns:
            (是否有效, 错误列表)
        """
        errors = []
        performance = config.performance
        
        # 检查超时时间
        if performance.page_load_timeout < 1000:
            errors.append("页面加载超时时间不能少于1000毫秒")
        
        if performance.element_wait_timeout < 1000:
            errors.append("元素等待超时时间不能少于1000毫秒")
        
        # 检查截图质量
        if not 1 <= performance.screenshot_quality <= 100:
            errors.append("截图质量必须在1-100范围内")
        
        # 检查缓存大小
        if performance.cache_size < 0:
            errors.append("缓存大小不能为负数")
        
        return len(errors) == 0, errors
    
    def validate_all(self, config_path: str) -> Dict[str, Any]:
        """
        执行完整的配置验证
        
        Args:
            config_path: 配置文件路径
            
        Returns:
            验证结果字典
        """
        result = {
            "valid": True,
            "errors": [],
            "warnings": [],
            "config": None
        }
        
        # 验证配置文件
        file_valid, file_errors, config = self.validate_config_file(config_path)
        if not file_valid:
            result["valid"] = False
            result["errors"].extend(file_errors)
            return result
        
        result["config"] = config
        
        # 验证环境变量
        env_valid, env_errors = self.validate_environment_variables()
        if not env_valid:
            result["valid"] = False
            result["errors"].extend(env_errors)
        
        # 验证各个配置模块
        validators = [
            ("代理配置", self.validate_proxy_config),
            ("AI配置", self.validate_ai_config),
            ("日志配置", self.validate_logging_config),
            ("安全配置", self.validate_security_config),
            ("性能配置", self.validate_performance_config),
        ]
        
        for name, validator in validators:
            try:
                valid, errors = validator(config)
                if not valid:
                    result["valid"] = False
                    result["errors"].extend([f"{name}: {error}" for error in errors])
            except Exception as e:
                result["valid"] = False
                result["errors"].append(f"{name}验证失败: {e}")
        
        return result
    
    def generate_validation_report(self, config_path: str) -> str:
        """
        生成验证报告
        
        Args:
            config_path: 配置文件路径
            
        Returns:
            验证报告文本
        """
        result = self.validate_all(config_path)
        
        report = []
        report.append("=" * 50)
        report.append("配置验证报告")
        report.append("=" * 50)
        report.append(f"配置文件: {config_path}")
        report.append(f"验证时间: {Path().cwd()}")
        report.append("")
        
        if result["valid"]:
            report.append("✅ 配置验证通过")
        else:
            report.append("❌ 配置验证失败")
        
        if result["errors"]:
            report.append("")
            report.append("错误列表:")
            for i, error in enumerate(result["errors"], 1):
                report.append(f"  {i}. {error}")
        
        if result["warnings"]:
            report.append("")
            report.append("警告列表:")
            for i, warning in enumerate(result["warnings"], 1):
                report.append(f"  {i}. {warning}")
        
        if result["config"]:
            report.append("")
            report.append("配置摘要:")
            config = result["config"]
            report.append(f"  - 浏览器: {'无头模式' if config.browser.headless else '有头模式'}")
            report.append(f"  - 代理: {'启用' if config.browser.proxy.enabled else '禁用'}")
            report.append(f"  - 日志级别: {config.logging.level}")
            report.append(f"  - AI模型: {config.ai.model.text}")
            report.append(f"  - 加密: {'启用' if config.security.encryption_enabled else '禁用'}")
        
        report.append("")
        report.append("=" * 50)
        
        return "\n".join(report)


def main():
    """命令行入口"""
    import argparse
    
    parser = argparse.ArgumentParser(description="配置验证工具")
    parser.add_argument("config_path", help="配置文件路径")
    parser.add_argument("--report", "-r", help="保存验证报告到文件")
    
    args = parser.parse_args()
    
    validator = ConfigValidator()
    
    if args.report:
        report = validator.generate_validation_report(args.config_path)
        with open(args.report, 'w', encoding='utf-8') as f:
            f.write(report)
        print(f"验证报告已保存到: {args.report}")
    else:
        result = validator.validate_all(args.config_path)
        if result["valid"]:
            print("✅ 配置验证通过")
        else:
            print("❌ 配置验证失败")
            for error in result["errors"]:
                print(f"  - {error}")


if __name__ == "__main__":
    main()